package cn.jingyuan.swan.gw.service.impl;

import cn.jingyuan.bee.fastjson.FastJsonUtils;
import cn.jingyuan.bee.spring.utils.WebUtils;
import cn.jingyuan.swan.gw.constants.RequestConstants;
import cn.jingyuan.swan.gw.service.AccessLogService;
import cn.jingyuan.swan.system.web.restful.model.GatewayAccessLogRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.util.AntPathMatcher;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

@Slf4j
@Service
public class AccessLogServiceImpl implements AccessLogService {

    private final AntPathMatcher antPathMatcher = new AntPathMatcher();

    // @Resource
    // GatewayAccessLogService accessLogService;

    Set<String> ignores = new HashSet<>(Arrays.asList(
        "/**/oauth/check_token",
        "/**/webjars/**"
    ));

    @Override
    public void sendLog(HttpServletRequest request, HttpServletResponse response, Exception ex) {
        String path = request.getRequestURI();
        if (this.ignoreLog(path)) {
            return;
        }

        try {
            Integer httpStatus = response.getStatus();
            String method = request.getMethod();
            String serviceId = (String) request.getAttribute(FilterConstants.SERVICE_ID_KEY);
            String ip = WebUtils.getRemoteAddress(request);
            Date requestTime = (Date) request.getAttribute(RequestConstants.HEADER_REQUEST_TIME);
            Map<String, String> headers = WebUtils.getHeaders(request);
            String userAgent = headers.get(HttpHeaders.USER_AGENT);


            // FIXME 优化日志信息,不进行用户信息检查,否则影响性能

            Map<String, Object> userDetailsMap = null;
            // try {
            // DefaultUserDetails userDetails = DefaultOAuth2Helper.getUser();
            // userDetailsMap = BeanUtils.beanToMap(userDetails);
            // } catch (Exception e) {
            //     log.debug(e.getMessage(), e);
            // }


            String error = null;
            if (null != ex) {
                error = ex.getMessage();
            }


            GatewayAccessLogRequest accessLog = new GatewayAccessLogRequest();
            accessLog.setServiceId(serviceId);
            accessLog.setPath(path);
            accessLog.setMethod(method);
            // accessLog.setParams();
            accessLog.setHeaders(headers);
            accessLog.setUserAgent(userAgent);
            accessLog.setRequestTime(requestTime);
            accessLog.setIp(ip);
            accessLog.setAuthentication(userDetailsMap);
            accessLog.setHttpStatus(httpStatus.toString());
            accessLog.setResponseTime(new Date());
            accessLog.setError(error);


            String accessLogJson = FastJsonUtils.json(accessLog);
            log.debug("Access Log Content: {}", accessLogJson);

            // FIXME body 太大，不能使用 feign 发送，考虑 mq 投递
            // accessLogService.saveLog(accessLog);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    /**
     * 忽略日志记录
     */
    public boolean ignoreLog(String path) {
        Iterator<String> iterator = ignores.iterator();
        while (iterator.hasNext()) {
            String url = iterator.next();
            if (antPathMatcher.match(url, path)) {
                return true;
            }
        }
        return false;
    }

}
